package com.s7175.kor.gui;

import javax.swing.JFrame;

import edu.pjwstk.kor.queries.KORQueries;

import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;

import com.db4o.ObjectContainer;
import com.s7175.kor.data.DB40Data;
import com.s7175.kor.gui.datahandling.DataHandler;
import com.s7175.kor.gui.datahandling.DatabankBridge;
import com.s7175.kor.gui.queries.QueriesName;
import com.s7175.kor.gui.queries.QueryTableModel;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JTextField;

import pl.wcislo.sbql4j.java.model.runtime.Struct;

import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.RowSpec;
import com.jgoodies.forms.factories.FormFactory;

import javax.swing.JLabel;
import javax.swing.JButton;

import java.awt.Font;
import java.util.Collection;

import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.JSeparator;

/**
 * @author Tomasz
 *
 */
public class MainWindow {
	private JFrame mainWindow;
	private KORQueries queries;
	private final DB40Data data;
	private final DatabankBridge dbHandler;
	private final ObjectContainer dbConn;
	private JButton btnExecuteQuerie;
	private JLabel queryName;
	private JTextField param1;
	private JTextField param2;
	private JTextField param3;
	private JLabel lblParam;
	private JLabel lblParam_1;
	private JLabel lblParam_2;
	private JLabel queryLabel;
	private QueriesName currentQuery;
	private JTable queryTable;

	public DB40Data getData() {
		return data;
	}

	public DatabankBridge getDbHandler() {
		return dbHandler;
	}

	public ObjectContainer getDbConnection() {
		return dbConn;
	}

	public MainWindow(KORQueries queries) {
		this.queries = queries;
		this.data = new DB40Data();
		this.dbConn = this.data.getConnection();
		this.dbHandler = new DatabankBridge(data);
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		mainWindow = new JFrame();
		mainWindow.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.out.println("Close connection");
				dbConn.close();
			}
		});
		mainWindow.setTitle("Main Window");
		mainWindow.setBounds(100, 100, 1024, 600);
		mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		JMenuBar menuBar = new JMenuBar();
		mainWindow.setJMenuBar(menuBar);

		JMenu mnNewMenu = new JMenu("Queries");
		menuBar.add(mnNewMenu);
		
				JMenuItem mntmNewMenuItem = new JMenuItem("allServerWhereDomain");
				mntmNewMenuItem.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						setQuery(QueriesName.allServerWhereDomain,true,false,false);
						setText("Server where domain == ?","Server.domain =", "fe.de.bosch.com");
					}
				});
				mnNewMenu.add(mntmNewMenuItem);
		
				JMenuItem mntmNewMenuItem_1 = new JMenuItem(
						"allComponentsWhereAttribute");
				mntmNewMenuItem_1.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						setQuery(QueriesName.allComponentsWhereAttribute,true,false,false);
						setText("( Attribute where name == ? ).(component.name, value)","Attribute.name =", "RESPONSIBLE");
					}
				});
				mnNewMenu.add(mntmNewMenuItem_1);
		
		JMenuItem mntmNewMenuItem_2 = new JMenuItem("allServersWithConfiuguration");
		mntmNewMenuItem_2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.allServersWithConfiuguration,false,false,false);
				setText("Server join ConfItem");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_2);
		
		JMenuItem mntmNewMenuItem_3 = new JMenuItem("allConfigurationForComponent");
		mntmNewMenuItem_3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.allConfigurationForComponent,true,false,false);
				setText("((Component where name == ?).servers).ConfItem","Component.name =", "Feuerbach");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_3);
		
		JMenuItem mntmNewMenuItem_4 = new JMenuItem("allServerInComponentWithPareameters");
		mntmNewMenuItem_4.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.allServerInComponentWithPareameters,true,true,false);
				setText("((Component where name == ?).servers) join ConfItem.((parameters where name == ?).value)",
						"Component.name == ?", "Stuttgart",
						"parameters.name == ?","USERS_COUNT");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_4);
		
		JSeparator separator_3 = new JSeparator();
		mnNewMenu.add(separator_3);
		
		JMenuItem mntmNewMenuItem_15 = new JMenuItem("serverUsersPerCore");
		mntmNewMenuItem_15.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.serverUsersPerCore,false,false,false);
				setText("Server.(name as SERVER_NAME, ConfItem.users/ConfItem.cores as USERS_PER_CORES, ConfItem.users%ConfItem.cores as MODULO_USERS_PER_CORES)");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_15);
		
		JMenuItem mntmNewMenuItem_16 = new JMenuItem("plusHowManyUsersOnServers");
		mntmNewMenuItem_16.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.plusHowManyUsersOnServers,true,true,false);
				setText("((Server where name == ?).ConfItem.users as FIRST,(Server where name == ?).ConfItem.users as SEC).(FIRST+SEC)",
						"FIRST_SERVER.name == ?", "FE0VMC0484",
						"SECOND_SERVER.name == ?","FE0VMC0477");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_16);
		
		JMenuItem mntmNewMenuItem_17 = new JMenuItem("configurationWithoutDebug");
		mntmNewMenuItem_17.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.configurationWithoutDebug,false,false,false);
				setText("Configuration where not debug");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_17);
		
		JMenuItem mntmNewMenuItem_18 = new JMenuItem("andMark");
		mntmNewMenuItem_18.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.andMark,true,true,false);
				setText("(Configuration where cores > ? and cores < ?).(WorksOn.name as SERVER_NAME,WorksOn.domain as SERVER_DOMAIN)",
						"cores > ?", "3",
						"cores < ?","7");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_18);
		
		JSeparator separator_2 = new JSeparator();
		mnNewMenu.add(separator_2);
		
		JMenuItem mntmNewMenuItem_5 = new JMenuItem("orderByWithOwnComperator");
		mntmNewMenuItem_5.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.orderByWithOwnComperator,false,false,false);
				setText("Server as SERVERS order by SERVERS.domain; SERVERS.name using myComparator");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_5);
		
		JSeparator separator = new JSeparator();
		mnNewMenu.add(separator);
		
		JMenuItem mntmNewMenuItem_13 = new JMenuItem("serverCount");
		mntmNewMenuItem_13.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.serverCount,true,false,false);
				setText("count (Component where name == ?).servers",
						"Component.name ==","Stuttgart");
			}
		});
		
		JMenuItem mntmNewMenuItem_10 = new JMenuItem("isAllConfItemOver");
		mntmNewMenuItem_10.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.isAllConfItemOver,true,true,false);
				setText("all ((Component where name == ?).servers.ConfItem)(users > ?)",
						"Component.name ==","Cluster Varitas 1",
						"User amount > ?","0");
			}
		});
		
		JMenuItem mntmNewMenuItem_6 = new JMenuItem("anyServerFromWithMoreUserThan");
		mntmNewMenuItem_6.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.anyServerFromWithMoreUserThan,true,true,false);
				setText("any ((Component where name == ?).servers).configuration as confs (confs.users > 5000)",
						"Component.name == ?", "Cluster Varitas 1",
						"confs.users > ?","5422");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_6);
		mnNewMenu.add(mntmNewMenuItem_10);
		mnNewMenu.add(mntmNewMenuItem_13);
		
		JMenuItem mntmNewMenuItem_11 = new JMenuItem("componentsWithCoresAverage");
		mntmNewMenuItem_11.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.componentsWithCoresAverage,true,false,false);
				setText("Component.(name, avg(servers group as serv.(serv.ConfItem.cores)) as average) where average > ?",
						"average > ?","0");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_11);
		
		JMenuItem mntmNewMenuItem_7 = new JMenuItem("minMaxOfUser");
		mntmNewMenuItem_7.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.minMaxOfUser,false,false,false);
				setText("(Configuration.users group as totalusers).(min(totalusers) as MIN_USERS, max(totalusers) as MAX_USERS)");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_7);
		
		JSeparator separator_1 = new JSeparator();
		mnNewMenu.add(separator_1);
		
		JMenuItem mntmNewMenuItem_8 = new JMenuItem("closeByWithHierarchy");
		mntmNewMenuItem_8.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.closeByWithHierarchy,true,false,false);
				setText("<html>(Configuration where name==?).<br/>(worksOn.name as servername, (parameters) group as CONFITEM_PARAMS, worksOn.worksIn as DIRECT_COMPONENT,<br/>(worksOn.worksIn close by parent) group as HIERARCHY)</br>",
						"confiuguration.name == ?","Apache 2.2.22");
			}
		});
		
		JMenuItem mntmNewMenuItem_9 = new JMenuItem("allServersMinusServersFromComponent");
		mntmNewMenuItem_9.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.allServersMinusServersFromComponent,true,false,false);
				setText("((Server minus (Component where name == ?).servers) join worksIn.(name as COMPO_NAME)) order by COMPO_NAME",
						"Component.name == ?","Stuttgart");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_9);
		mnNewMenu.add(mntmNewMenuItem_8);
		
		JMenuItem mntmNewMenuItem_14 = new JMenuItem("intersectConfItem");
		mntmNewMenuItem_14.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.intersectConfItem,true,true,false);
				setText("((Configuration where users > ?) intersect (Configuration where cores < 8))",
						"Users Amount > ?","800",
						"Cores Amount < ?","8");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_14);
		
		JMenuItem mntmNewMenuItem_12 = new JMenuItem("unionServersWithCoreUser");
		mntmNewMenuItem_12.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.unionServersWithCoreUser,true,true,false);
				setText("((Server where ConfItem.cores == ?) union (Server where ConfItem.users > ?))",
						"Cores Amount == ?","16",
						"Users Amount > ?","5000");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_12);
		
		JSeparator separator_4 = new JSeparator();
		mnNewMenu.add(separator_4);
		
		JMenuItem mntmNewMenuItem_19 = new JMenuItem("martwePodZapytanie");
		mntmNewMenuItem_19.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.martwePodZapytanie,false,false,false);
				setText("(Server as serv join serv.ConfItem).serv.domain");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_19);
		
		JMenuItem mntmNewMenuItem_20 = new JMenuItem("zPetla");
		mntmNewMenuItem_20.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setQuery(QueriesName.zPetla,true,false,false);
				setText("Component.(name, avg(servers group as serv.(serv.ConfItem.cores)) as average) where (average*10) > ?",
						"(average*10) > ?","0");
			}
		});
		mnNewMenu.add(mntmNewMenuItem_20);

		JMenu menu = new JMenu("Data Handler");
		menuBar.add(menu);

		JMenuItem menuItem = new JMenuItem("Open data handeler");
		menuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				DataHandler dataHandlerFrame = new DataHandler(data, dbHandler);
				dataHandlerFrame.setVisible(true);
			}
		});
		menu.add(menuItem);
		mainWindow.getContentPane().setLayout(
				new FormLayout(new ColumnSpec[] {
				FormFactory.RELATED_GAP_COLSPEC,
				ColumnSpec.decode("default:grow"),},
			new RowSpec[] {
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC,
				FormFactory.RELATED_GAP_ROWSPEC,
				RowSpec.decode("max(59dlu;default):grow"),}));
		
				queryName = new JLabel("Plese use Queries menu");
				queryName.setFont(new Font("Tahoma", Font.BOLD, 14));
				mainWindow.getContentPane().add(queryName, "2, 2, center, default");
		
		queryLabel = new JLabel("");
		queryLabel.setEnabled(false);
		queryLabel.setVisible(false);
		queryLabel.setFont(new Font("Tahoma", Font.BOLD, 11));
		mainWindow.getContentPane().add(queryLabel, "2, 4, center, center");

		lblParam = new JLabel("Param 1");
		mainWindow.getContentPane().add(lblParam, "2, 6");

		param1 = new JTextField();

		mainWindow.getContentPane().add(param1, "2, 8, fill, top");
		param1.setColumns(10);

		lblParam_1 = new JLabel("Param 2");
		mainWindow.getContentPane().add(lblParam_1, "2, 10");

		param2 = new JTextField();
		mainWindow.getContentPane().add(param2, "2, 12, fill, default");
		param2.setColumns(10);

		lblParam_2 = new JLabel("Param 3");
		mainWindow.getContentPane().add(lblParam_2, "2, 14");

		param3 = new JTextField();
		mainWindow.getContentPane().add(param3, "2, 16, fill, default");
		param3.setColumns(10);

		btnExecuteQuerie = new JButton("Execute query");
		btnExecuteQuerie.setEnabled(false);
		btnExecuteQuerie.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				execute();
			}
		});
		mainWindow.getContentPane().add(btnExecuteQuerie, "2, 18");

		JLabel lblResult = new JLabel("Result");
		mainWindow.getContentPane().add(lblResult, "2, 20");
		
		queryTable = new JTable();
		queryTable.setVisible(false);
		JScrollPane queryTableScroll = new JScrollPane(queryTable);
		queryTableScroll.setEnabled(false);
		mainWindow.getContentPane().add(queryTableScroll, "2, 22, fill, fill");
		
		
		lblParam.setVisible(false);
		lblParam_1.setVisible(false);
		lblParam_2.setVisible(false);
		param1.setVisible(false);
		param2.setVisible(false);
		param3.setVisible(false);
		
		mainWindow.setVisible(true);
	}

	private void execute() {
		if (currentQuery != null) {
			switch (currentQuery) {
			case allServerWhereDomain:
				doTable(queries.allServerWhereDomain(param1.getText()));
				break;
			case allComponentsWhereAttribute:
				doTable(queries.allComponentsWhereAttribute(param1
						.getText()));
				break;
			case allServersWithConfiuguration:
				doTable(queries.allServersWithConfiuguration());
				break;
			case allConfigurationForComponent:
				doTable(queries.allConfigurationForComponent(param1.getText()));
				break;
			case allServerInComponentWithPareameters:
				doTable(queries.allServerInComponentWithPareameters(param1.getText(),param2.getText()));
				break;
			case orderByWithOwnComperator:
				doTable(queries.orderByWithOwnComperator());
				break;
			case anyServerFromWithMoreUserThan:
				doTable(queries.anyServerFromWithMoreUserThan(param1.getText(),Integer.parseInt(param2.getText())));
				break;
			case minMaxOfUser:
				doTable(queries.minMaxOfUser());
				break;
			case closeByWithHierarchy:
				doTable(queries.closeByWithHierarchy(param1.getText()));
				break;
			case allServersMinusServersFromComponent:
				doTable(queries.allServersMinusServersFromComponent(param1.getText()));
				break;
			case isAllConfItemOver:
				doTable(queries.isAllConfItemOver(param1.getText(),Integer.parseInt(param2.getText())));
				break;
			case componentsWithCoresAverage:
				doTable(queries.componentsWithCoresAverage(Integer.parseInt(param1.getText())));
				break;
			case unionServersWithCoreUser:
				doTable(queries.unionServersWithCoreUser(Integer.parseInt(param1.getText()),Integer.parseInt(param2.getText())));
				break;
			case serverCount:
				doTable(queries.serverCount(param1.getText()));
				break;
			case intersectConfItem:
				doTable(queries.intersectConfItem(Integer.parseInt(param1.getText()),Integer.parseInt(param2.getText())));
				break;
			case serverUsersPerCore:
				doTable(queries.serverUsersPerCore());
				break;
			case plusHowManyUsersOnServers:
				doTable(queries.plusHowManyUsersOnServers(param1.getText(),param2.getText()));
				break;
			case configurationWithoutDebug:
				doTable(queries.configurationWithoutDebug());
				break;
			case andMark:
				doTable(queries.andMark(Integer.parseInt(param1.getText()),Integer.parseInt(param2.getText())));
				break;
			case martwePodZapytanie:
				doTable(queries.martwePodZapytanie());
				break;
			case zPetla:
				doTable(queries.zPetla(Integer.parseInt(param1.getText())));
				break;
			}
			queryTable.setVisible(true);
		} else {
			JOptionPane.showMessageDialog(new JFrame(),
					"You have to choose query!", "Application error",
					JOptionPane.ERROR_MESSAGE);
		}

	}
	
	private void doTable(Collection<Struct> data){
		QueryTableModel qtm;
	    qtm = new QueryTableModel();
		qtm.setQuery(data);
		queryTable.setModel(qtm);
	}
	private void doTable(Struct data){
		QueryTableModel qtm;
	    qtm = new QueryTableModel();
		qtm.setQuery(data);
		queryTable.setModel(qtm);
	}
	
	private void setQuery(QueriesName q, boolean p1,boolean p2, boolean p3){
		currentQuery = q;
		queryLabel.setVisible(true);
		queryTable.setModel(new DefaultTableModel(new Object[][] {},new Object[] {}));
		queryTable.setVisible(false);
		queryName.setText(splitCamelCase(q.toString()));
		btnExecuteQuerie.setEnabled(true);
		lblParam.setVisible(p1);
		lblParam_1.setVisible(p2);
		lblParam_2.setVisible(p3);
		param1.setVisible(p1);
		param2.setVisible(p2);
		param3.setVisible(p3);
	}
	
	private void setText(String... inputs){
		String[] aTexts = new String[7];
		if(inputs.length < 7){
			for(int i = 0;i < 7;++i){
				aTexts[i] = i<inputs.length ? inputs[i] : ""; 		
			}
		}
		queryLabel.setText(aTexts[0]);
		lblParam.setText(aTexts[1]);
		param1.setText(aTexts[2]);
		lblParam_1.setText(aTexts[3]);
		param2.setText(aTexts[4]);
		lblParam_2.setText(aTexts[5]);
		param3.setText(aTexts[6]);
	}

	static String splitCamelCase(String s) {
		return s.replaceAll(String.format("%s|%s|%s",
				"(?<=[A-Z])(?=[A-Z][a-z])", "(?<=[^A-Z])(?=[A-Z])",
				"(?<=[A-Za-z])(?=[^A-Za-z])"), " ");
	}

}
